#pragma once

#include "Direct3DEnums.h"
#include "Direct3DMacros.h"
#include "Direct3DIncludes.h"

//Direct3D Framework
class Direct3DFramework
{
public:
	//attributes & members
	WindowAppFramework* m_window;

	LPDIRECT3D9       m_object;
	LPDIRECT3DDEVICE9 m_device;

	LPD3DXLINE m_line;
	LPD3DXFONT m_font;

	D3DPRESENT_PARAMETERS m_present;
	D3DDISPLAYMODE        m_display;
	D3DCAPS9              m_capability;

	LPDIRECT3DSURFACE9           m_surfBack;
	LPDIRECT3DVERTEXDECLARATION9 m_vertDeclMesh;
	LPDIRECT3DVERTEXDECLARATION9 m_vertDeclQuad;

	float m_camAspect;
	float m_camNear;
	float m_camFar;
	float m_camFov;
	D3DXVECTOR3 m_camPos;
	D3DXVECTOR3 m_camLook;
	D3DXVECTOR3 m_camUp;
	D3DXVECTOR3 m_camRight;
	D3DXMATRIX  m_view;
	D3DXMATRIX  m_proj;
	D3DFQuad    m_screenQuad[4];
	D3DFQuad    m_spriteQuad[4];

	DCamera                m_cCamera;
	D3DFEffect*            m_cEffect;
	DMaterial              m_cMaterial;
	DLight                 m_cLight;
	LPDIRECT3DTEXTURE9     m_cTexture2D[6];
	LPDIRECT3DCUBETEXTURE9 m_cTexture3D[6];

	List<D3DFEffect*>    m_effectList;
	List<D3DFTexture2D*> m_texture2DList;
	List<D3DFTexture3D*> m_texture3DList;
	List<D3DFMesh*>      m_meshList;
	List<D3DFSurface*>   m_surfaceList;

	//ctor & dtor
	Direct3DFramework();
	~Direct3DFramework();

	//init functions
	int init(WindowAppFramework* a_window, bool a_vsync);

	//release functions
	int release();

	//create functions
	int createEffect(DEffect* a_effect, char* a_path);
	int createTexture2D(DTexture2D* a_texture, int a_width, int a_height, int a_format);
	int createTexture2D(DTexture2D* a_texture, char* a_path);
	int createTexture3D(DTexture3D* a_texture, char* a_path);
	int createMesh(DMesh* a_mesh, char* a_path);
	int createSurface(DSurface* a_surface, int a_type);
	int createSurface(DSurface* a_surface, DTexture2D* a_texture);

	//update function
	int updateCamera(DCamera& a_camera);
	int updateTransform(
		DMesh* a_mesh,
		V3DF a_cen,
		V3DF a_trn,
		V3DF a_scl,
		V3DF a_rot,
		V3DF* a_look  = 0,
		V3DF* a_right = 0);
	int updateTransform(
		DTexture2D* a_texture,
		V2DF  a_cen,
		V2DF  a_trn,
		V2DF  a_scl,
		float a_rot);

	//draw functions
	int drawBegin();
	int drawEnd();
	int drawQuad();
	int drawMesh(DMesh* a_mesh);
	int drawTexture2D(DTexture2D* a_texture);
	int drawText(char* a_text, V2DF a_pos, int a_color);

	//surface functions
	int surfaceSave();
	int surfaceLoad();
	int surfaceClear();
	int surfaceSwap(DSurface* a_surfRT);

	//setter functions
	int setEffect(DEffect* a_effect);
	int setTechnique(char* a_technique);
	int setMaterial(DMaterial* a_material);
	int setLight(DLight* a_light);
	int setTexture2D(DTexture2D* a_texture, int a_number);
	int setTexture3D(DTexture3D* a_texture, int a_number);

	//math functions
	int projCoord(
		DMesh* a_mesh,
		bool*  a_hit,
		float* a_dis,
		V3DF*  a_ori,
		V3DF*  a_dir,
		V2DF   a_pos);
};